﻿/// <reference path="jquery-1.4.1-vsdoc.js" />
/// <reference path="crafty-min.js" />

jQuery(function ($) { // window.onload might be slow, opted for jQuery(window).ready() instead
    var 
    // Some useful constant declarations:
    SPEED = 4,
    WIDTH = 640,
    HEIGHT = 480,
    TILE_SIZE = 16,

    // encapsulated Crafty engine startup routine (should be the first thing executed):
    initGame = function (containerId) {
        Crafty.init(WIDTH, HEIGHT);
        $(Crafty.stage.elem).appendTo($("<div />", {
            id: "game-container"
        }).css({
            display: "block", margin: "auto", width: "640px"
        }).prependTo("#main"));
    };

    // start up the Crafty engine:
    initGame();

    // @scene
    // define the loading screen that will display while our assets load.
    // <summary>This scene quietly sets up the game, hiding it with a splash screen while dependent resources and components are loaded.</summary>
    Crafty.scene("loading", function () {

        // set a black background with some loading text:
        Crafty.background("#333");
        Crafty.e("2D, DOM, Text").attr({ w: WIDTH, h: 16, x: 0, y: (HEIGHT / 2) })
        .text("Loading...")
        .css({ "text-align": "center", color: "white" });

        // load takes an array of assets and a callback when complete:
        Crafty.load(["sprite.png"], function () {
            Crafty.scene("main"); // when everything is loaded, run the main scene
        });

        // load ALL required Crafty components!

        // @component
        // define a custom renderable Crafty character component
        Crafty.c("Character", {

            character: function () {
                // event handler that changes the direction of this entity 
                var onNewDirection = function (direction) {
                    if (direction.x < 0) {
                        if (!this.isPlaying("walk_left"))
                            this.stop().animate("walk_left", 10, -1);
                    }
                    if (direction.x > 0) {
                        if (!this.isPlaying("walk_right"))
                            this.stop().animate("walk_right", 10, -1);
                    }
                    if (direction.y < 0) {
                        if (!this.isPlaying("walk_up"))
                            this.stop().animate("walk_up", 10, -1);
                    }
                    if (direction.y > 0) {
                        if (!this.isPlaying("walk_down"))
                            this.stop().animate("walk_down", 10, -1);
                    }
                    if (!direction.x && !direction.y) {
                        this.stop();
                    }
                },

                // event handler that responds to change in state when this entity is moved
                onMoved = function (from) {
                    if (this.hit('solid') || this.hit('player')) {
                        this.attr({ x: from.x, y: from.y });
                    }
                };

                // setup animations from sprites:
                this.requires("SpriteAnimation, Collision, Grid")
                .animate("walk_left", 6, 3, 8)
                .animate("walk_right", 9, 3, 11)
                .animate("walk_up", 3, 3, 5)
                .animate("walk_down", 0, 3, 2)

                // binds event handler to the direction-changed event
                .bind("NewDirection", onNewDirection)

                // event handler for when this entity hits another solid entity
                .onHit("solid", function () {
                    // Move unit out of solid tile
                })
                // event handler for when this entity hits another player entity
                .onHit("player", function () {
                    // Move unit out of solid tile
                })
                // binds event handler to the entity-moved event
                .bind('Moved', onMoved);
                return this;
            }
        });

        // @components
        // turn the sprite map into usable components
        Crafty.sprite(TILE_SIZE, "sprite.png", {
            grass1: [0, 0],
            grass2: [1, 0],
            grass3: [2, 0],
            grass4: [3, 0],
            flower: [0, 1],
            bush1: [0, 2],
            bush2: [1, 2],
            player: [0, 3],
            enemy: [0, 3],
            banana: [4, 0],
            empty: [4, 0]
        });

        // @component
        // define a custom left (WASD) keyboard controls component
        Crafty.c("LeftControls", {

            init: function () {
                this.requires('Multiway');
            },

            leftControls: function (speed) {
                this.multiway(speed, { W: -90, S: 90, D: 0, A: 180 })
                return this;
            }
        });

        // @component
        // define a custom right (IJKL) keyboard controls component
        Crafty.c("RightControls", {

            init: function () {
                this.requires('Multiway');
            },

            rightControls: function (speed) {
                this.multiway(speed, { I: -90, K: 90, L: 0, J: 180 })
                return this;
            }
        });
    });

    // @scene
    // define the main game routine.
    // <summary>This scene prepares the game for use, initializing and rendering the game environment and constructing the player entities.</summary>
    Crafty.scene("main", function () {

        // @initializer
        // method to generate the map:
        var generateWorld = function () {
            // loop through all tiles
            for (var i = 0; i < WIDTH / TILE_SIZE; i++) {
                for (var j = 0; j < HEIGHT / TILE_SIZE; j++) {

                    // place grass on all tiles:
                    grassType = Crafty.math.randomInt(1, 4);
                    Crafty.e("2D, DOM, grass" + grassType)
                    .attr({ x: i * TILE_SIZE, y: j * TILE_SIZE, z: 1 });

                    // create a fence of bushes:
                    if (i === 0 || i === WIDTH / TILE_SIZE - 1 || j === 0 || j === HEIGHT / TILE_SIZE - 1) {
                        Crafty.e("2D, DOM, solid, bush" + Crafty.math.randomInt(1, 2))
                        .attr({ x: i * TILE_SIZE, y: j * TILE_SIZE, z: 2 });
                    }
                    // create a grid of bushes:
                    if ((i % 4 === 0) && (j % 4 === 0)) {
                        Crafty.e("2D, DOM, solid, bush1")
                        .attr({ x: i * TILE_SIZE, y: j * TILE_SIZE, z: 2000 })
                    }
                }
            }
        };

        // execute the world generation routine
        generateWorld();

        // once the environment is initialized and ready for the player entities:

        // @entity
        // player 1 entity containing some preloaded components:
        Crafty.e("2D, DOM, Character, player, LeftControls")
        .attr({ x: TILE_SIZE, y: HEIGHT - TILE_SIZE * 2, z: 1 })
        .leftControls(SPEED)
        .character();

        // @entity
        // player 2 entity containing some preloaded components:
        Crafty.e("2D, DOM, Character, player, RightControls")
        .attr({ x: WIDTH - TILE_SIZE * 2, y: TILE_SIZE, z: 1 })
        .rightControls(SPEED)
        .character();
    });

    // automatically execute the loading scene once the above definitions have been completely compiled and loaded
    Crafty.scene("loading");
});
